package com.android.readcard.utils.djlm.DJLMReader3.djlm_xieka;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.android.readcard.utils.djlm.DJLMReader3.reader.HexUtil;
import com.inuker.bluetooth.library.BluetoothClient;
import com.inuker.bluetooth.library.Constants;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.connect.response.BleNotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleUnnotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleWriteResponse;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.utils.BluetoothUtils;

import java.util.UUID;

public class DJLMSimTools extends Thread {
    private static final String TAG = "写卡";

    private static final UUID RX_SERVICE_UUID = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
    private static final UUID TX_CHAR_UUID = UUID.fromString("0000fff4-0000-1000-8000-00805f9b34fb");
    private static final UUID RX_CHAR6_UUID = UUID.fromString("0000fff6-0000-1000-8000-00805f9b34fb");
    private static final UUID RX_CHAR7_UUID = UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb");

    public static final int TYPE_ICCID = 1;
    public static final int TYPE_SIM = 2;
    public static final int TYPE_ICCID_SIM = 3;
    public static final int TYPE_WRITE_SIM = 4;

    private static final int STEP_IMSI = 10;
    private static final int STEP_FILE = 12;
    private static final int STEP_SMSCENTER = 11;
    private static final int STEP_DONE = 13;

    private Context mContext;
    private String macAddress;
    private DJLMSimCallBack callBack;
    private int type = 0;
    private DJLMSimTools djlmSimTools;
    private boolean isRuning = false;
    private BluetoothClient mBluetooth;
    private String phoneNum = "";//短信中心号
    private String imsi = "";//写卡数据
    private boolean isNew = false;//判断设备类型  true 新类型  false  老设备
    private boolean isSuccess = false;
    private int currentStep = 0;
    private int writeStep = STEP_FILE;//写卡步骤管理
    private String tempICCID = "";
    private String[] commandICCID = {"0207A0A40000023F00", "0207A0A40000022FE2", "0205A0B000000A"};
    private String[] commandSIM = {"0207A0A40000023F00", "0207A0A40000027F20", "0207A0A40000026F07", "0205A0B0000009"};
    private String[] commandSMSCenter = {"0207A0A40000023F00", "0207A0A40000027F10", "0207A0A40000026F42"};
    private boolean isReadICCIDandSIM = false;
    private boolean isDone = false;
    private String result = "";
    private int imsiStep = 0;

    public DJLMSimTools(Context context, String macAddress, DJLMSimCallBack callBack) throws Exception {
        if (context == null || TextUtils.isEmpty(macAddress) || callBack == null) {
            throw new Exception("关键参数不能为空");
        }
        this.mContext = context;
        this.macAddress = macAddress;
        this.callBack = callBack;
        this.djlmSimTools = this;
    }

    Handler mHander = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1001 && !isDone) {
                // isSuccess = false;
                isDone = true;
                mHander.removeMessages(1001);
                if (!isSuccess) {
                    result = "操作超时，请检测数据是否正确!";
                    if (isReadICCIDandSIM) {
                        callBack.errror(TYPE_ICCID_SIM, result);
                    } else {
                        callBack.errror(type, result);
                    }
                }
                close();
                return;
            }
            mHander.removeMessages(1001);

            if (msg.what == 1) {
                result = msg.obj.toString();
                isSuccess = true;
                isDone = true;
                sendBeep();
            } else {
                // isSuccess = false;
                isDone = true;
                if (!isSuccess) {
                    result = msg.obj.toString();
                    if (isReadICCIDandSIM) {
                        callBack.errror(TYPE_ICCID_SIM, result);
                    } else {
                        callBack.errror(type, result);
                    }
                }

                close();
            }

        }
    };

    private void close() {
        try {

            Log.e(TAG, "开始回收资源....");
            if (mBluetooth != null) {
                mBluetooth.unnotify(macAddress, RX_SERVICE_UUID, TX_CHAR_UUID, mBleUnnotifyResponse);
                mBluetooth.clearRequest(macAddress, Constants.REQUEST_WRITE);
                mBluetooth.clearRequest(macAddress, Constants.REQUEST_READ);
                mBluetooth.refreshCache(macAddress);
                mBluetooth.disconnect(macAddress);
            }
            mBluetooth = null;
            if (isSuccess) {
                if (type == TYPE_ICCID) {
                    callBack.success(type, result);
                } else if (type == TYPE_SIM) {
                    if (!TextUtils.isEmpty(tempICCID)) {
                        callBack.success(TYPE_ICCID_SIM, result);
                    } else {
                        callBack.success(type, result);
                    }
                } else if (type == TYPE_WRITE_SIM) {
                    callBack.success(type, result);
                }
            }
            Log.e(TAG, "回收完毕....");
            interrupt();
        } catch (Exception ex) {
            Log.e(TAG, "close: ex", ex);
        }
    }

    /***
     * 读取ICCID
     */
    public DJLMSimTools readICCID() {
        this.type = TYPE_ICCID;
        isReadICCIDandSIM = false;
        return this;
    }

    /***
     * 读取SIM
     */
    public DJLMSimTools readSIM() {
        this.type = TYPE_SIM;
        isReadICCIDandSIM = false;
        return this;
    }

    /***
     * 读取SIM 和ICCID  格式ICCID|SIM
     */
    public DJLMSimTools readICCID_SIM() {
        this.type = TYPE_ICCID_SIM;
        isReadICCIDandSIM = true;
        return this;
    }

    /****
     * 写卡
     * @param imsi 写入的SIM号
     * @param smsCenterPhone 短信中心号
     */
    public DJLMSimTools writeSIM(String imsi, String smsCenterPhone) {
        this.type = TYPE_WRITE_SIM;
        this.phoneNum = smsCenterPhone;
        this.imsi = imsi;
        isReadICCIDandSIM = false;
        return this;
    }

    @Override
    public void run() {

        Log.e(TAG, "run: 任务开始" + System.currentTimeMillis());
        isRuning = true;
        mHander.removeMessages(1001);
        mHander.sendEmptyMessageDelayed(1001, 40 * 1000);
        if (type == TYPE_WRITE_SIM) {
            try {
                Log.e(TAG, "run: 写卡之前休息2秒.....");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Log.e(TAG, "run:开始连接蓝牙..." + System.currentTimeMillis());
        connectedBle();
    }

    private void step1() {
        currentStep = 0;
        tempICCID = "";
        isSuccess = false;
        isRuning = true;

        if (!isNew) {
            Log.e(TAG, "step1: 发送高低速切换....");
            writeBle("0C0100");//高低速切换 老版本
        }
        if (type == TYPE_ICCID || type == TYPE_ICCID_SIM) {
            writeBle(commandICCID[currentStep]);
        } else if (type == TYPE_SIM) {
            writeBle(commandSIM[currentStep]);
        } else if (type == TYPE_WRITE_SIM) {

            writeBle(commandSMSCenter[currentStep]);
        }
    }

    private void sendMessage(int what, String msg) {

        Message message = new Message();
        message.what = what;
        message.obj = msg;
        mHander.sendMessage(message);
        //  if (mBluetooth != null && mBluetooth.getConnectStatus(macAddress) == Constants.REQUEST_SUCCESS) {
        //      mBluetooth.unnotify(macAddress, RX_SERVICE_UUID, TX_CHAR_UUID, mBleUnnotifyResponse);
        //  }

    }

    /****
     * 蓝牙连接
     */
    private void connectedBle() {
        try {
            mBluetooth = new BluetoothClient(mContext);
            mBluetooth.stopSearch();
            mBluetooth.disconnect(macAddress);
            mBluetooth.disconnect(macAddress);

            BleConnectOptions options = new BleConnectOptions.Builder()
                    .setConnectRetry(3)   // 连接如果失败重试3次
                    .setConnectTimeout(5000)   // 连接超时15s
                    .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
                    .setServiceDiscoverTimeout(5000)  // 发现服务超时2s
                    .build();
            mBluetooth.connect(macAddress, options, new BleConnectResponse() {
                @Override
                public void onResponse(int code, BleGattProfile data) {
                    Log.e(TAG, "蓝牙连接: " + code);
                    if (code == Constants.REQUEST_SUCCESS) {
                        try {
                            isNew = BluetoothUtils.getRemoteDevice(macAddress).getName().trim().toLowerCase().startsWith("djlm3");
                        } catch (Exception ex) {
                        }

                        Log.i(TAG, "connectedBle: 是否新版:" + isNew + "名字" + BluetoothUtils.getRemoteDevice(macAddress).getName());
                        // writeBle2("0C0101");//高速模式
                        //成功连接
                        mBluetooth.unnotify(macAddress, RX_SERVICE_UUID, TX_CHAR_UUID, mBleUnnotifyResponse);
                        //注册通知
                        mBluetooth.notify(macAddress, RX_SERVICE_UUID, TX_CHAR_UUID, mBleNotifyResponse);
                        step1();
                        //
                    } else {
                        Log.e(TAG, "无法初始化蓝牙服务！");

                        sendMessage(-1, "无法连接蓝牙设备，请重试");
                    }
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
            sendMessage(-1, "无法连接蓝牙设备，请重试");
        }
    }

    String imsi_cmd = "";

    /***
     * 写入SIM卡
     * @param msg
     */

    private void WRITESIM(byte[] msg) {

//        if (msg != null && "0000".equals(HexUtil.bin2HexStr(msg)) && writeStep != STEP_IMSI && writeStep != STEP_SMSCENTER) {
//            return;
//        }

        if (writeStep == STEP_FILE) {
            byte[] data = null;
            data = vertifyReadDirData(msg);
            if (data == null) {
                //出错。。。。验证失败
                Log.e(TAG, "WRITESIM: 验证失败步骤:" + currentStep);
                sendMessage(-1, "无法读取写卡文件数据,请重试");
                return;
            }
            Log.e(TAG, "写卡:" + HexUtil.bin2HexStr(data));
            currentStep++;
            if (currentStep < commandSMSCenter.length) {
                //写卡
                writeBle(commandSMSCenter[currentStep]);
                return;
            } else {
                imsiStep = 0;
                writeStep = STEP_SMSCENTER;
            }
        }


        //写入操作  先选择文件 再写入   总写 2 个文件  一个是 IMSI  一个是 短信中心号
        if (writeStep == STEP_IMSI) {
            String hex = HexUtil.bin2HexStr(msg);

            Log.e(TAG, "开始写IMSI了" + hex);
            if (hex == null || hex.length() < 2) {
                //写入短信中心号失败
                Log.e(TAG, "WRITESIM: 写入短信中心号失败");
                sendMessage(-1, "写入短信中心号失败,请重试");
                return;
            }
            if (imsiStep == 0) {
                if (!hex.endsWith("9000")) {
                    //写入短信中心号失败，也许不是白卡。
                    Log.e(TAG, "WRITESIM: 写入短信中心号失败，也许不是白卡。");
                    sendMessage(-1, "写入短信中心号失败,请重试");
                    return;
                }
                String newimsi = "809" + imsi;
                newimsi = receivedStrToReversedStr(newimsi);
                if (TextUtils.isEmpty(newimsi) || imsi.length() < 10) {
                    //处理失败 IMSI 长度有问题
                    Log.e(TAG, "WRITESIM: 处理失败 IMSI 长度有问题");
                    sendMessage(-1, "写卡失败 IMSI 长度有问题");
                    return;
                }
                imsi_cmd = "A0F4000012" + newimsi + newimsi;
                Log.i(TAG, "WRITESIM: imsi_cmd=" + imsi_cmd);
                String cmd1 = "031000" + imsi_cmd.substring(0, 30);
                Log.e(TAG, "WRITESIM: 第一个命令:" + cmd1);
                imsiStep++;
                writeBle(cmd1);

            } else if (imsiStep == 1) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                String cmd2 = "03090F" + imsi_cmd.substring(30);
                Log.e(TAG, "WRITESIM: 第2个命令:" + cmd2);
                imsiStep++;
                writeBle(cmd2);
            } else if (imsiStep == 2) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String cmd3 = "040117";
                Log.e(TAG, "WRITESIM: 第3个命令:" + cmd3);
                writeBle(cmd3);
                writeStep = STEP_DONE;
            }

        } else if (writeStep == STEP_SMSCENTER) {
            Log.e(TAG, "开始写SMS了" + HexUtil.bin2HexStr(msg));
            //"031000A0DC010428FFFFFFFFFFFFFFFFFFFF", "03100FFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", "04012D"}
            if (imsiStep == 0) {
                imsiStep++;
                writeBle("031000A0DC010428FFFFFFFFFFFFFFFFFFFF");
            } else if (imsiStep == 1) {
                imsiStep++;
                writeBle("03100FFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
            } else if (imsiStep == 2) {
                imsiStep++;
                writeBle(getSMSCenterFormat(this.phoneNum));
            } else {
                imsiStep = 0;
                writeStep = STEP_IMSI;
                writeBle("04012D");
            }


        } else if (writeStep == STEP_DONE) {
            String hex = HexUtil.bin2HexStr(msg);
            Log.e(TAG, "WRITESIM: 写卡结果:" + hex);

            if (TextUtils.isEmpty(hex) || hex.length() < 2) {
                //
                Log.e(TAG, "WRITESIM: 写入IMSI失败。。。");
                sendMessage(-1, "写入IMSI失败，重试");
                return;
            }
            if (!hex.endsWith("9000")) {
                if (hex.endsWith("9804")) {
                    Log.e(TAG, "WRITESIM: 次卡不是白卡，是已经成卡，请换卡");
                    sendMessage(-1, "次卡不是白卡，可能是成卡，请换卡重新写卡");
                    return;
                }
                Log.e(TAG, "WRITESIM: 写卡失败,错误代码:" + hex);
                sendMessage(-1, "写卡失败，请重试 错误代码:" + hex);
                return;
            }
            Log.e(TAG, "WRITESIM: 写卡成功:" + hex);
            sendMessage(1, "写卡成功!");
            return;


        }

    }

    /***
     * 获取短信中心号的格式字符
     * @param smsCenterNumber
     * @return
     */
    private String getSMSCenterFormat(String smsCenterNumber) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("801986");
        stringBuffer.append(smsCenterNumber);
        stringBuffer.append("F");
        smsCenterNumber = receivedStrToReversedStr(stringBuffer.toString());
        stringBuffer = new StringBuffer();
        stringBuffer.append("03101E");
        stringBuffer.append(smsCenterNumber);
        stringBuffer.append("FFFFFFFFFFFF");
        return stringBuffer.toString();
    }

    private String receivedStrToReversedStr(String strData) {

        if (TextUtils.isEmpty(strData)) {
            //字符串不能为空
            return "";
        }
        if (strData.length() % 2 != 0) {
            //必须要2的倍数
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0, len = strData.length() - 1; i < len; i = i + 2) {
            sb.append(strData.charAt(i + 1));
            sb.append(strData.charAt(i));
        }
        return sb.toString();


    }

    /****
     * 读取SIM 步骤管理
     * @param msg
     */
    private void SIM(byte[] msg) {
        byte[] data = null;
        if (currentStep == commandSIM.length - 1) {
            data = vertifyReadFileData(msg);
        } else {
            data = vertifyReadDirData(msg);
        }
        if (data == null) {
            sendMessage(-1, "无法读取SIM,请重试");
            return;
        }
        Log.e(TAG, "读取sim:" + HexUtil.bin2HexStr(data));

        currentStep++;
        if (currentStep < commandSIM.length) {
            //写卡
            writeBle(commandSIM[currentStep]);
            return;
        }

        String sim = GetRevBCDString(data);
        Log.e(TAG, "sim:" + sim);
        if (TextUtils.isEmpty(sim) || sim.length() <= 7) {
            //读取SIM失败
            Log.e(TAG, "读取SIM失败:" + sim);
            sendMessage(-1, "无法读取SIM,请重试");
            return;
        }
        sim = sim.substring(7);
        if (type == TYPE_SIM) {
            //读取ICCID成功
            Log.e(TAG, "读取sim成功:" + sim);
            if (!TextUtils.isEmpty(tempICCID)) {
                Log.e(TAG, "读取sim成功:" + sim + " ICCID=" + tempICCID);
                sendMessage(1, tempICCID + "|" + sim);
                return;
            }
            sendMessage(1, sim);
        }
    }

    private void sendBeep() {

        Log.e(TAG, "sendBeep: 发送Beep了》。。。。");
        byte[] query = HexUtil.hexStringToBytes("0A0131");
        mBluetooth.writeNoRsp(macAddress, RX_SERVICE_UUID, RX_CHAR7_UUID, query, mBleWriteResponse);
    }

    private void sendVerstionCommand() {

        byte[] query = HexUtil.hexStringToBytes("0B0131");
        mBluetooth.write(macAddress, RX_SERVICE_UUID, RX_CHAR7_UUID, query, mBleWriteResponse);
    }

    private void writeBle(String cmd) {
        byte[] query = HexUtil.hexStringToBytes(cmd);
        // mBluetooth.write(macAddress, RX_SERVICE_UUID, RX_CHAR7_UUID, query, mBleWriteResponse);
        mBluetooth.writeNoRsp(macAddress, RX_SERVICE_UUID, RX_CHAR7_UUID, query, mBleWriteResponse);
    }


    /****
     * 读取ICCID 步骤管理
     * @param msg
     */
    private void ICCID(byte[] msg) {
        byte[] data = null;
        if (currentStep == commandICCID.length - 1) {
            data = vertifyReadFileData(msg);
        } else {
            data = vertifyReadDirData(msg);
        }
        Log.i(TAG, "ICCID:" + HexUtil.bin2HexStr(msg));
        if (data == null) {
            //读取失败///
            Log.i(TAG, "ICCID: 验证失败" + HexUtil.bin2HexStr(msg));
            sendMessage(-1, "无法读取ICCID,请重试");
            return;
        }
        currentStep++;
        if (currentStep < commandICCID.length) {
            //写卡
            writeBle(commandICCID[currentStep]);
            return;
        }
        Log.e(TAG, "读取ICCID完毕:" + HexUtil.bin2HexStr(data));
        String iccid = GetRevBCDString(data);
        if (TextUtils.isEmpty(iccid)) {
            //读取ICCID失败
            sendMessage(-1, "无法读取ICCID,请重试");
            return;
        }
        iccid = iccid.substring(4);
        tempICCID = iccid;
        if (type == TYPE_ICCID) {
            //读取ICCID成功
            Log.e(TAG, "读取ICCID成功:" + iccid);
            sendMessage(1, iccid);
        } else if (type == TYPE_ICCID_SIM) {
            type = TYPE_SIM;
            currentStep = 0;
            writeBle(commandSIM[currentStep]);
        }
    }

    BleWriteResponse mBleWriteResponse = new BleWriteResponse() {
        @Override
        public void onResponse(int code) {

            Log.e(TAG, "写入状态回调: code = " + code + " TYPE=" + type + "  isICCDAndIMSI=" + isReadICCIDandSIM);
            if (code == Constants.REQUEST_SUCCESS) {
                //mHandler.sendEmptyMessage(ErrorCode.ERROR_CODE1);
            } else {
                sendMessage(-1, "无法写入数据，请重试");
            }
        }
    };

    //蓝牙返回的数据通知
    private BleNotifyResponse mBleNotifyResponse = new BleNotifyResponse() {
        @Override
        public void onNotify(UUID service, UUID character, byte[] retValue) {
            if (retValue != null && "0000".equals(HexUtil.bin2HexStr(retValue))) {
                Log.i(TAG, "onNotify: 返回了0000");
                if (type == TYPE_WRITE_SIM) {
                    if (writeStep == STEP_IMSI || writeStep == STEP_SMSCENTER) {
                        WRITESIM(retValue);
                        return;
                    }
                }
                if (isSuccess) {
                    close();
                }
                return;
            }
            if (type == TYPE_ICCID || type == TYPE_ICCID_SIM) {
                ICCID(retValue);
            } else if (type == TYPE_SIM) {
                SIM(retValue);
            } else if (type == TYPE_WRITE_SIM) {
                WRITESIM(retValue);
            }

        }

        @Override
        public void onResponse(int code) {
            Log.e(TAG, "读取状态: code = " + code);
            if (code == Constants.REQUEST_SUCCESS) {
            } else {
                sendMessage(-1, "无法读取蓝牙数据，请检查写入的数据是否正确");
            }
        }
    };

    /**
     * 验证文件夹
     *
     * @param value
     * @return
     */
    public byte[] vertifyReadDirData(byte[] value) {
        byte[] SW = new byte[2];
        Log.i("蓝牙", "vertifyReadFileData: z最后验证" + value.length);
        if (value.length > 2) {
            SW[0] = value[value.length - 2];
            SW[1] = value[value.length - 1];
            byte[] data = new byte[value.length - 2];
            System.arraycopy(value, 0, data, 0, value.length - 2);
            if (data != null || SW[0] != (byte) 0x9F) {
                return data;
            }
        }
        return null;
    }

    /**
     * 验证数据 并处理返回
     *
     * @param value
     * @return
     */
    public byte[] vertifyReadFileData(byte[] value) {
        byte[] SW = new byte[2];
        Log.i("蓝牙", "vertifyReadFileData: z最后验证" + value.length);
        if (value.length > 2) {
            SW[0] = value[value.length - 2];
            SW[1] = value[value.length - 1];
            byte[] data = new byte[value.length - 2];
            System.arraycopy(value, 0, data, 0, value.length - 2);
            if (data != null && SW[0] == (byte) 0x90 && SW[1] == 0x00) {
                return data;
            }
        }
        return null;
    }

    /**
     * 类型转换
     *
     * @param data
     * @return
     */
    private String GetRevBCDString(byte[] data) {
        byte[] temp = new byte[data.length * 2];
        for (int i = 0; i < data.length; i++) {
            if ((data[i] & 0xf) >= 0 && (data[i] & 0xf) <= 9) {
                temp[i * 2] = (byte) ((data[i] & 0xf) + '0');
            } else if ((data[i] & 0xf) >= 0xa && (data[i] & 0xf) <= 0xf) {
                temp[i * 2] = (byte) ((data[i] & 0xf) + 'A' - 10);
            } else {
                temp[i * 2] = '?';
            }

            if (((data[i] >> 4) & 0xf) >= 0 && ((data[i] >> 4) & 0xf) <= 9) {
                temp[i * 2 + 1] = (byte) (((data[i] >> 4) & 0xf) + '0');
            } else if (((data[i] >> 4) & 0xf) >= 0xa && ((data[i] >> 4) & 0xf) <= 0xf) {
                temp[i * 2 + 1] = (byte) (((data[i] >> 4) & 0xf) + 'A' - 10);
            } else {
                temp[i * 2] = '?';
            }
        }
        String strRet = new String(temp);
        return strRet;
    }

    BleUnnotifyResponse mBleUnnotifyResponse = new BleUnnotifyResponse() {
        @Override
        public void onResponse(int code) {

        }
    };


}
